package initialize

import (
	"context"
	"encoding/json"
	"fmt"
	"go_final/mxshop_srvs/inventory_srv/global"
	"go_final/mxshop_srvs/inventory_srv/model"

	"gorm.io/gorm"

	"go.uber.org/zap"

	"github.com/apache/rocketmq-client-go/v2"
	"github.com/apache/rocketmq-client-go/v2/consumer"
	"github.com/apache/rocketmq-client-go/v2/primitive"
)

func InitRocketmqListener() {
	c, _ := rocketmq.NewPushConsumer(
		consumer.WithNameServer([]string{"120.24.67.46:9876"}),
		consumer.WithGroupName("testGroup"),
	)
	err := c.Subscribe(
		"order_reback",
		consumer.MessageSelector{},
		autoRebackInventory,
	)

	if err != nil {
		panic("订阅MQ消息失败")
	}

	err = c.Start()
	if err != nil {
		fmt.Println("err", err)
		panic("开始订阅MQ消息失败")
	}
}

// autoRebackInventory 监听到归还订单消息以后调用归还库存接口
func autoRebackInventory(ctx context.Context,
	msgs ...*primitive.MessageExt) (consumer.ConsumeResult, error) {
	type OrderInfo struct{ OrderSn string }

	for i := range msgs {
		fmt.Printf("收到消息咯....: %v \n", msgs[i])
		// 这个接口应该确保幂等性, 保证一个订单的库存不能多次归还, 没有扣减的库存不能归还
		// 新建一张表, 这个表记录了详细的订单扣减细节, 以及归还细节
		var orderInfo OrderInfo
		err := json.Unmarshal(msgs[i].Body, &orderInfo)
		if err != nil {
			zap.S().Errorf("解析json失败: %s", err.Error())
			return consumer.ConsumeSuccess, nil
		}

		// 去将Inventory的库存加回去, 将shelldetail的status设置为2
		tx := global.DB.Begin()
		var sellDetail model.StocksSellDetail
		res := tx.Where(&model.StocksSellDetail{
			OrderSn: orderInfo.OrderSn,
			Status:  1,
		}).First(&sellDetail)
		if res.Error != nil {
			zap.S().Info("执行sql出错了: %s", res.Error.Error())
			return consumer.ConsumeSuccess, nil
		}
		if res.RowsAffected == 0 {
			// 没有查询到需要归还的记录
			return consumer.ConsumeSuccess, nil
		}

		// 查询到了, 逐个归还商品库存扣减记录
		for _, orderGoods := range sellDetail.Detail {
			res := tx.Model(model.Inventory{}).Where(model.Inventory{
				GoodsID: orderGoods.Goods,
			}).Update("stocks", gorm.Expr("stocks + ?", orderGoods.Num))

			if res.Error != nil {
				tx.Rollback()
				return consumer.ConsumeRetryLater, nil
			}

			if res.RowsAffected == 0 {
				tx.Rollback()
				return consumer.ConsumeRetryLater, nil
			}
		}

		res = tx.Model(model.StocksSellDetail{}).Where(model.StocksSellDetail{
			OrderSn: orderInfo.OrderSn,
		}).Update("status", 2)
		if res.Error != nil {
			tx.Rollback()
			return consumer.ConsumeRetryLater, nil
		}

		if res.RowsAffected == 0 {
			tx.Rollback()
			return consumer.ConsumeRetryLater, nil
		}
		tx.Commit()
		// 如果业务逻辑有错误, 那么可以return consumer.ConsumeRetryLater, nil
		return consumer.ConsumeSuccess, nil
	}

	return consumer.ConsumeSuccess, nil
}
